import { onMounted, onUnmounted, ref, h, reactive, watch } from 'vue'
import { notification, Button, Descriptions } from 'ant-design-vue'
import mqtt from 'mqtt/dist/mqtt.min'
import { useUserStore } from '@/store/modules/user'
import { SmileOutlined } from '@ant-design/icons-vue'

// GasDetector, FireDetector, Fire
// Water、Ammeter、Gas
// Environment
interface AlarmType {
  deviceTypes: string[]
}

export function useAlarmInfo({ deviceTypes = [] }: AlarmType) {
  console.log('进入监听页面：', deviceTypes)

  const receivedMessages = ref()
  const subscribedSuccess = ref(false)
  const retryTimes = ref(0)
  const client = ref({
    connected: false,
  } as mqtt.MqttClient)
  const userStore = useUserStore()
  const userinfo = userStore.getUserInfo

  const connectionState = reactive({
    // ws or wss
    protocol: 'ws',
    host: '172.16.70.159',
    // host: '120.92.208.117',
    port: 8083,
    clientId: 'mqtt_' + Math.random().toString(16).substring(2, 8),
    username: 'admin',
    password: 'public',
    clean: true,
    connectTimeout: 30 * 1000, // ms
    reconnectPeriod: 4000, // ms
  })

  // topic & QoS for MQTT subscribing
  const subscription = ref({
    topic: `/push/alarm/${userinfo.userId}`,
    qos: 0 as mqtt.QoS,
  })

  // topic, QoS & payload for publishing message
  // const publish = ref({
  //   topic: 'topic/browser',
  //   qos: 0 as mqtt.QoS,
  //   payload: '{ "msg": "Hello, I am browser." }',
  // })

  const initData = () => {
    client.value = {
      connected: false,
    } as mqtt.MqttClient
    retryTimes.value = 0
    subscribedSuccess.value = false
  }

  const handleOnReConnect = () => {
    retryTimes.value += 1
    if (retryTimes.value > 5) {
      try {
        client.value.end()
        initData()
        console.log('connection maxReconnectTimes limit, stop retry')
      } catch (error) {
        console.log('handleOnReConnect catch error:', error)
      }
    }
  }

  // create MQTT connection
  const createConnection = () => {
    try {
      const { protocol, host, port, ...options } = connectionState
      const connectUrl = `${protocol}://${host}:${port}/mqtt`
      /**
       * /mqtt: MQTT-WebSocket uniformly uses /path as the connection path,
       * which should be specified when connecting, and the path used on EMQX is /mqtt.
       * for more details about "mqtt.connect" method & options,
       * please refer to https://github.com/mqttjs/MQTT.js#mqttconnecturl-options
       */
      client.value = mqtt.connect(connectUrl, options)

      if (client.value.on) {
        // https://github.com/mqttjs/MQTT.js#event-connect
        client.value.on('connect', () => {
          console.log('websocket连接已建立...')
        })

        // https://github.com/mqttjs/MQTT.js#event-reconnect
        client.value.on('reconnect', handleOnReConnect)

        // https://github.com/mqttjs/MQTT.js#event-error
        client.value.on('error', (error) => {
          console.log('连接异常:', error)
        })

        // https://github.com/mqttjs/MQTT.js#event-message
        client.value.on('message', (topic: string, message) => {
          receivedMessages.value = JSON.parse(message)
          // receivedMessages.value = receivedMessages.value.concat(message.toString())
          console.log(`接收到服务器消息: ${message} from topic: ${topic}`)
          const isExist = deviceTypes.includes(receivedMessages.value.data.deviceTypeCode)
          isExist && openNotification()
        })
      }
    } catch (error) {
      console.log('mqtt.connect error:', error)
    }
  }

  // subscribe topic
  // https://github.com/mqttjs/MQTT.js#mqttclientsubscribetopictopic-arraytopic-object-options-callback
  const doSubscribe = () => {
    const { topic, qos } = subscription.value
    client.value.subscribe(topic, { qos }, (error: Error, granted: mqtt.ISubscriptionGrant[]) => {
      if (error) {
        console.log('订阅错误:', error)
        return
      }
      subscribedSuccess.value = true
      console.log('订阅成功:', granted)
    })
  }

  // unsubscribe topic
  // https://github.com/mqttjs/MQTT.js#mqttclientunsubscribetopictopic-array-options-callback
  const doUnSubscribe = () => {
    const { topic, qos } = subscription.value
    client.value.unsubscribe(topic, { qos }, (error) => {
      subscribedSuccess.value = false
      if (error) {
        console.log('unsubscribe error:', error)
        return
      }
      console.log(`取消订阅topic: ${topic}`)
    })
  }

  // publish message 不需要走发布消息逻辑，只保留代码
  // https://github.com/mqttjs/MQTT.js#mqttclientpublishtopic-message-options-callback
  // const doPublish = () => {
  //   const { topic, qos, payload } = publish.value
  //   client.value.publish(topic, payload, { qos }, (error) => {
  //     if (error) {
  //       console.log('publish error:', error)
  //       return
  //     }
  //     console.log(`published message: ${payload}`)
  //   })
  // }

  // disconnect
  // https://github.com/mqttjs/MQTT.js#mqttclientendforce-options-callback
  const destroyConnection = () => {
    if (client.value.connected) {
      try {
        client.value.end(false, () => {
          initData()
          console.log('成功关闭websocket连接')
        })
      } catch (error) {
        console.log('disconnect error:', error)
      }
    }
  }

  // 定义一个组件，可以包含任何复杂的结构
  const ComplexDescription = {
    setup() {
      // 使用响应式变量
      const reactiveContent = ref(receivedMessages.value)
      let keyValueData = reactive({})

      // 监听响应式变量的变化
      watch(
        () => receivedMessages.value,
        (newValue) => {
          reactiveContent.value = newValue
        },
      )
      console.log('reactvie', reactiveContent.value)
      // 假设我们有一个键值对对象
      keyValueData = {
        报警名称: reactiveContent.value?.data?.alarmRuleName || '0',
        报警类型: reactiveContent.value?.data?.alarmRuleName || '0',
        // 报警等级: reactiveContent.value?.data?.alarmRuleName || '',
        报警时间: reactiveContent.value?.data?.alarmTime || '0',
        报警描述: reactiveContent.value?.data?.alarmContent || '0',
      }

      // 创建一个响应式对象
      const styleObject = reactive({
        color: '#fff',
        fontSize: '12px',
        backgroundColor: '#09334b',
        display: 'flex',
      })

      return () =>
        h(
          'div',
          {},
          Object.entries(keyValueData).map(([key, value]) =>
            h('div', { style: styleObject }, [
              h(
                'div',
                {
                  class: 'key',
                  style: { fontWeight: '900', fontSize: '14px', whiteSpace: 'nowrap', flexItem: 1 },
                },
                `${key}: `,
              ),
              h('div', { class: 'value', style: { marginLeft: '10px' } }, value),
            ]),
          ),
        )
    },
  }

  const openNotification = () => {
    const key = `open${Date.now()}`
    notification.open({
      message: '',
      placement: 'bottomRight',
      class: 'notification-custom-class',
      style: { backgroundColor: '#09334b' },
      icon: () => h(SmileOutlined, { style: 'color: #ff0000' }),
      duration: 0,
      description: () => h(ComplexDescription),
      btn: () =>
        h(
          Button,
          {
            type: 'primary',
            size: 'small',
            onClick: () => notification.close(key),
          },
          { default: () => '关闭' },
        ),
      key,
      onClose: close,
    })
  }

  const close = () => {
    console.log(
      'Notification was closed. Either the close button was clicked or duration time elapsed.',
    )
  }

  onMounted(() => {
    createConnection()
    console.log('进入页面开始订阅消息, 当前用户信息为：', userinfo.userId, userinfo.userName)
    doSubscribe()
  })

  // onUnmounted时取消订阅并关闭连接
  onUnmounted(() => {
    doUnSubscribe()
    destroyConnection()
    console.log('切换页面，需要订阅并关闭连接')
  })
}
